package com.zusmart.core.plugin.support;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.zusmart.base.activity.support.AbstractActivity;
import com.zusmart.base.logging.Logger;
import com.zusmart.base.logging.LoggerFactory;
import com.zusmart.base.util.Assert;
import com.zusmart.core.bean.BeanDefinitionRegistry;
import com.zusmart.core.plugin.Plugin;
import com.zusmart.core.plugin.PluginManager;

public abstract class AbstractPluginManager extends AbstractActivity<PluginManager> implements PluginManager {

	private static final Logger logger = LoggerFactory.getLogger(AbstractPluginManager.class);

	private final BeanDefinitionRegistry beanDefinitionRegistry;
	private final Map<Class<? extends Plugin>, Plugin> plugins = new LinkedHashMap<Class<? extends Plugin>, Plugin>();

	protected AbstractPluginManager(BeanDefinitionRegistry beanDefinitionRegistry) {
		Assert.isNull(beanDefinitionRegistry, "bean definition registry must not be null");
		this.beanDefinitionRegistry = beanDefinitionRegistry;
	}

	@Override
	public BeanDefinitionRegistry getBeanDefinitionRegistry() {
		return this.beanDefinitionRegistry;
	}

	@Override
	public void attachPlugin(Plugin plugin) {
		if (null == plugin) {
			return;
		}
		if (this.existsPlugin(plugin.getClass())) {
			return;
		}
		try {
			if (this.isRunning()) {
				plugin.start();
			}
			this.plugins.put(plugin.getClass(), plugin);
		} catch (Exception e) {
			logger.warn(e.getMessage());
		}
	}

	@Override
	public void detachPlugin(Plugin plugin) {
		if (null == plugin) {
			return;
		}
		if (this.existsPlugin(plugin.getClass())) {
			try {
				plugin.close();
				this.plugins.remove(plugin.getClass());
			} catch (Exception e) {
				logger.warn(e.getMessage());
			}
		}
	}

	@Override
	public boolean existsPlugin(Class<? extends Plugin> pluginType) {
		return null != pluginType && this.plugins.containsKey(pluginType);
	}

	@Override
	public Plugin getPlugin(Class<? extends Plugin> pluginType) {
		return this.plugins.get(pluginType);
	}

	@Override
	public Map<Class<? extends Plugin>, Plugin> getPlugins() {
		return Collections.unmodifiableMap(this.plugins);
	}

	@Override
	protected PluginManager getActivity() {
		return this;
	}

	@Override
	protected void doStart() throws Exception {
		for (Entry<Class<? extends Plugin>, Plugin> entry : this.plugins.entrySet()) {
			try {
				entry.getValue().start();
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
	}

	@Override
	protected void doClose() throws Exception {
		for (Entry<Class<? extends Plugin>, Plugin> entry : this.plugins.entrySet()) {
			try {
				entry.getValue().close();
			} catch (Exception e) {
				logger.error(e.getMessage());
			}
		}
	}
	
}